module et {
    export class EntityFactory {
        public static createWithParent<T extends Entity>(type: { new(): T }, parent: Entity, isFromPool?: boolean): T;
        public static createWithParent<T extends Entity, A>(type: { new(): T }, parent: Entity, a: A, isFromPool?: boolean): T;
        public static createWithParent<T extends Entity, A, B>(type: { new(): T }, parent: Entity, a: A, b: B, isFromPool?: boolean): T;
        public static createWithParent<T extends Entity, A, B, C>(type: { new(): T }, parent: Entity, a: A, b: B, c: C, isFromPool?: boolean): T;
        public static createWithParent<T extends Entity, A, B, C>(type: { new(): T }, parent: Entity, a?: A, b?: B, c?: C, isFromPool = false): T {
            let component = Entity.create(type, isFromPool);
            component.id = IdGenerater.GenerateId();
            component.parent = parent;

            if (a == undefined && b == undefined && c == undefined) {
                EventSystem.Instance.awake(component);
            }
            else if (a != undefined && b == undefined && c == undefined) {
                EventSystem.Instance.awake(component, a);
            }
            else if (a != undefined && b != undefined && c == undefined) {
                EventSystem.Instance.awake(component, a, b);
            }
            else if (a != undefined && b != undefined && c != undefined) {
                EventSystem.Instance.awake(component, a, b, c);
            }
            return component as T;
        }
        public static createWithParentAndId<T extends Entity>(type: { new(): T }, parent: Entity, id: Long, isFromPool?: boolean): T;
        public static createWithParentAndId<T extends Entity, A>(type: { new(): T }, parent: Entity, id: Long, a: A, isFromPool?: boolean): T;
        public static createWithParentAndId<T extends Entity, A, B>(type: { new(): T }, parent: Entity, id: Long, a: A, b: B, isFromPool?: boolean): T;
        public static createWithParentAndId<T extends Entity, A, B, C>(type: { new(): T }, parent: Entity, id: Long, a: A, b: B, c: C, isFromPool?: boolean): T;
        public static createWithParentAndId<T extends Entity, A, B, C>(type: { new(): T }, parent: Entity, id: Long, a?: A, b?: B, c?: C, isFromPool = false): T {
            let component = Entity.create(type, isFromPool);
            component.id = id;
            component.parent = parent;

            if (a == undefined && b == undefined && c == undefined) {
                EventSystem.Instance.awake(component);
            }
            else if (a != undefined && b == undefined && c == undefined) {
                EventSystem.Instance.awake(component, a);
            }
            else if (a != undefined && b != undefined && c == undefined) {
                EventSystem.Instance.awake(component, a, b);
            }
            else if (a != undefined && b != undefined && c != undefined) {
                EventSystem.Instance.awake(component, a, b, c);
            }
            return component as T;
        }
        public static create<T extends Entity>(type: { new(): T }, domain: Entity, isFromPool?: boolean): T
        public static create<T extends Entity, A>(type: { new(): T }, domain: Entity, a: A, isFromPool?: boolean): T
        public static create<T extends Entity, A, B>(type: { new(): T }, domain: Entity, a: A, b: B, isFromPool?: boolean): T
        public static create<T extends Entity, A, B, C>(type: { new(): T }, domain: Entity, a: A, b: B, c: C, isFromPool?: boolean): T
        public static create<T extends Entity, A, B, C>(type: { new(): T }, domain: Entity, a?: A, b?: B, c?: C, isFromPool = false): T {
            let component = Entity.create(type, isFromPool);
            component.domain = domain;
            component.id = IdGenerater.GenerateId();
            if (a == undefined && b == undefined && c == undefined) {
                EventSystem.Instance.awake(component);
            }
            else if (a != undefined && b == undefined && c == undefined) {
                EventSystem.Instance.awake(component, a);
            }
            else if (a != undefined && b != undefined && c == undefined) {
                EventSystem.Instance.awake(component, a, b);
            }
            else if (a != undefined && b != undefined && c != undefined) {
                EventSystem.Instance.awake(component, a, b, c);
            }
            return component as T;
        }
        public static createWithId<T extends Entity>(type: { new(): T }, domain: Entity, id: Long, isFromPool?: boolean): T
        public static createWithId<T extends Entity, A>(type: { new(): T }, domain: Entity, id: Long, a: A, isFromPool?: boolean): T
        public static createWithId<T extends Entity, A, B>(type: { new(): T }, domain: Entity, id: Long, a: A, b: B, isFromPool?: boolean): T
        public static createWithId<T extends Entity, A, B, C>(type: { new(): T }, domain: Entity, id: Long, a: A, b: B, c: C, isFromPool?: boolean): T
        public static createWithId<T extends Entity, A, B, C>(type: { new(): T }, domain: Entity, id: Long, a?: A, b?: B, c?: C, isFromPool = false): T {
            let component = Entity.create(type, isFromPool);
            component.domain = domain;
            component.id = id;

            if (a == undefined && b == undefined && c == undefined) {
                EventSystem.Instance.awake(component);
            }
            else if (a != undefined && b == undefined && c == undefined) {
                EventSystem.Instance.awake(component, a);
            }
            else if (a != undefined && b != undefined && c == undefined) {
                EventSystem.Instance.awake(component, a, b);
            }
            else if (a != undefined && b != undefined && c != undefined) {
                EventSystem.Instance.awake(component, a, b, c);
            }
            return component as T;
        }
    }
}